home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-03 / realdir.zip / REALDIR.BAS < prev    next >
BASIC Source File  |  1991-12-30  |  26KB  |  879 lines

  1. 'RealDir.Bas version 1.00
  2. 'By Rich Geldreich December, 1991
  3. 'You may use this program in any way as you wish as long as
  4. 'you don't make any money off it before I know about it!
  5. 'For any questions, comments, write or call at...
  6. '410 Market St.
  7. 'Gloucester City, New Jersey 08030
  8. '(609)-456-0721
  9.  
  10. '$DYNAMIC
  11. DEFINT A-Z
  12.  
  13. DECLARE SUB RestorePath (A$)
  14. DECLARE SUB ChangeDrive (Drive$)
  15. DECLARE SUB Refresh (X, Y, Length)
  16. DECLARE SUB Sort (A$(), Low, High)
  17. DECLARE SUB GetDir (EntryName$(), Extension$(), EntryType(), DirNum, Path$, Status)
  18. DECLARE SUB SelectFile (FileName$, Status)
  19. DECLARE SUB MakeFrame (X1, Y1, X2, Y2)
  20.  
  21. DECLARE FUNCTION LogicalDrives (Drive$)
  22. DECLARE FUNCTION GetKey ()
  23. DECLARE FUNCTION CurrentPath$ ()
  24. DECLARE FUNCTION CurrentDrive$ ()
  25. DECLARE FUNCTION NumDrives ()
  26. DECLARE FUNCTION RandInt (Lower, Upper)
  27. DECLARE FUNCTION RealPath$ ()
  28.  
  29.  
  30. CONST True = -1, False = NOT True
  31. CONST File = 0, Directory = 1
  32. CONST Enter = 13, TabKey = 9
  33. CONST UpArrow = -72, DownArrow = -80
  34. CONST LeftArrow = -75, RightArrow = -77
  35. CONST BackSpace = 8
  36. CONST Home = -71, EndKey = -79, Esc = 27
  37.  
  38. TYPE FileFindBuf
  39.     DOS            AS STRING * 19
  40.     CreateTime     AS STRING * 1
  41.     Attributes     AS INTEGER
  42.     AccessTime     AS INTEGER
  43.     AccessDate     AS INTEGER
  44.     FileSize       AS LONG
  45.     FileName       AS STRING * 13
  46. END TYPE
  47.  
  48. TYPE Register
  49.     Ax    AS INTEGER
  50.     Bx    AS INTEGER
  51.     Cx    AS INTEGER
  52.     Dx    AS INTEGER
  53.     Bp    AS INTEGER
  54.     Si    AS INTEGER
  55.     Di    AS INTEGER
  56.     Flags AS INTEGER
  57.     Ds    AS INTEGER
  58.     Es    AS INTEGER
  59. END TYPE
  60. DIM SHARED ErrorStatus
  61.  
  62.  
  63. 'sample usage:
  64.  
  65.  
  66.  
  67. SCREEN 0, , 1, 1
  68.  
  69. CLS
  70. 'The next program line gets a filename from the user.
  71. 'Don't overlook that THE CURRENT DIRECTORY IS CHANGED(unless you
  72. 'use RealDir and RestoreDir)!!!
  73.  
  74. 'Status will be 2 if the user hits Escape.
  75. 'Status will be 1 if a file was selected.
  76.  
  77. 'OldPath$ = RealPath$
  78. SelectFile FileName$, Status
  79. 'RestorePath OldPath$
  80.  
  81.  
  82. CLS
  83. PRINT "Status returned:"; Status
  84. IF Status = 2 THEN
  85.     PRINT "Aborted."
  86. ELSE
  87.     PRINT "File selected: "; FileName$
  88. END IF
  89. END
  90.  
  91.  
  92. ErrorHandler:
  93.     ErrorStatus = True
  94. RESUME NEXT
  95.  
  96. REM $STATIC
  97. 'Changes current drive.
  98. SUB ChangeDrive (Drive$)
  99.     DIM InReg AS Register
  100.     InReg.Ax = &HE00
  101.     InReg.Dx = ASC(Drive$) - 65
  102.     CALL interrupt(&H21, InReg, InReg)
  103. END SUB
  104.  
  105. 'Returns current drive.
  106. FUNCTION CurrentDrive$
  107.     DIM InReg AS Register
  108.     InReg.Ax = &H1900
  109.     CALL interrupt(&H21, InReg, InReg)
  110.     CurrentDrive$ = CHR$(65 + InReg.Ax MOD 256)
  111. END FUNCTION
  112.  
  113. 'Returns current path(not a full path- the current drive must be added).
  114. '**********************************************************************
  115. 'WARNING: for some reason, if the drive isn't ready this sub will
  116. 'HANG UP!!! (the SelectFile sub makes sure the drive is ready)
  117. FUNCTION CurrentPath$
  118.         DIM InReg AS Register
  119.         DIM PathSize AS STRING * 64
  120.         InReg.Ax = &H4700
  121.         InReg.Dx = ASC(CurrentDrive$) - 64
  122.         InReg.Ds = VARSEG(PathSize)
  123.         InReg.Si = VARPTR(PathSize)
  124.         CALL InterruptX(&H21, InReg, InReg)
  125.         CurrentPath$ = LEFT$(PathSize, INSTR(PathSize, CHR$(0)) - 1)
  126. END FUNCTION
  127.  
  128. 'Generic Getdir subroutine. Status will be -1 if an error occurs.
  129. 'EntryName$() ,Extension$() and Entrytype will hold directory.
  130. 'EntryType() tells what the entry is(a FILE or DIRECTORY- see constants).
  131. 'Path$ must be full path + wildcard. ...like "c:\dos\*.*"
  132. 'If Path$ isn't found then Status will be -1.
  133. SUB GetDir (EntryName$(), Extension$(), EntryType(), DirNum, Path$, Status)
  134.  
  135.     DIM InReg AS Register, OutReg AS Register
  136.     DIM Buffer AS FileFindBuf
  137.      
  138.     DirNum = 0
  139.  
  140.  
  141.     InReg.Ax = &H1A00
  142.     InReg.Ds = VARSEG(Buffer)
  143.     InReg.Dx = VARPTR(Buffer)
  144.     CALL interrupt(&H21, InReg, OutReg)
  145.     InReg.Ax = &H4E00
  146.     InReg.Cx = 16
  147.     Npath$ = Path$ + CHR$(0)
  148.     InReg.Dx = SADD(Npath$)
  149.     CALL InterruptX(&H21, InReg, OutReg)
  150.     FirstFM = (OutReg.Ax AND &HF)
  151.     IF OutReg.Flags AND 1 THEN
  152.         Status = True
  153.         EXIT SUB
  154.     ELSE
  155.         Status = False
  156.     END IF
  157.   
  158.     IF FirstFM = 0 THEN
  159.         GOSUB MakeFile
  160.         DO
  161.             InReg.Ax = &H4F00
  162.             InReg.Dx = SADD(Npath$)
  163.             CALL interrupt(&H21, InReg, OutReg)
  164.             NextFM = OutReg.Ax AND &HF
  165.             IF NextFM = 0 THEN
  166.                 GOSUB MakeFile
  167.             END IF
  168.         LOOP WHILE NextFM = 0
  169.     END IF
  170.     EXIT SUB
  171.  
  172. MakeFile:
  173.     IF LEFT$(Buffer.FileName, 1) = "." THEN
  174.         RETURN
  175.     END IF
  176.  
  177.      
  178.     Entry$ = RTRIM$(Buffer.FileName)
  179.     IF Buffer.Attributes = 4096 THEN
  180.         EntryName$ = RTRIM$(LEFT$(Entry$, 8))
  181.         EntryType = Directory
  182.     ELSE
  183.         IF INSTR(Entry$, ".") = 0 THEN
  184.             EntryName$ = RTRIM$(LEFT$(Entry$, 8))
  185.             Extension$ = ""
  186.         ELSE
  187.             EntryName$ = LEFT$(Entry$, INSTR(Entry$, ".") - 1)
  188.             Extension$ = RTRIM$(LEFT$(MID$(Entry$, INSTR(Entry$, ".") + 1), 3))
  189.         END IF
  190.         EntryType = File
  191.     END IF
  192.     
  193.   
  194.     EntryName$(DirNum) = EntryName$
  195.     Extension$(DirNum) = Extension$
  196.     EntryType(DirNum) = EntryType
  197.  
  198.     DirNum = DirNum + 1
  199.  
  200.     Buffer.Attributes = 0
  201.     Buffer.AccessTime = 0
  202.     Buffer.AccessDate = 0
  203.     Buffer.FileSize = 0
  204.     Buffer.FileName = STRING$(13, 32)
  205. RETURN
  206.  
  207. END SUB
  208.  
  209. 'This sub returns the ascii keycode- extended keycodes(ones that have
  210. 'a zero as the first character) return easy to handle negative
  211. 'values.
  212. FUNCTION GetKey
  213.     DO
  214.         A$ = INKEY$
  215.     LOOP UNTIL A$ <> ""
  216.     IF LEN(A$) = 2 THEN
  217.         GetKey = -ASC(RIGHT$(A$, 1))
  218.     ELSE
  219.         GetKey = ASC(A$)
  220.     END IF
  221. END FUNCTION
  222.  
  223. FUNCTION LogicalDrives (Drive$)
  224.     DIM InReg AS Register
  225.     InReg.Ax = &H440E
  226.     InReg.Bx = ASC(Drive$) - 64
  227.     CALL interrupt(&H21, InReg, InReg)
  228.     IF (InReg.Flags AND 1) = 1 THEN
  229.         LogicalDrives = -1
  230.     ELSE
  231.         LogicalDrives = InReg.Ax AND 255
  232.     END IF
  233. END FUNCTION
  234.  
  235. 'Makes a frame in text mode. X1,Y1 start X2,Y2 end
  236. SUB MakeFrame (X1, Y1, X2, Y2)
  237.     UpLeft$ = "┌": UpRight$ = "┐": LoLeft$ = "└": LoRight$ = "┘"
  238.     H$ = "─": V$ = "│"
  239.     LOCATE Y1, X1
  240.     PRINT UpLeft$; STRING$(X2 - X1 - 1, H$); UpRight$;
  241.     LOCATE Y2, X1
  242.     PRINT LoLeft$; STRING$(X2 - X1 - 1, H$); LoRight$;
  243.     FOR Y = Y1 + 1 TO Y2 - 1
  244.         LOCATE Y, X1
  245.         PRINT V$;
  246.         LOCATE Y, X2
  247.         PRINT V$;
  248.     NEXT
  249. END SUB
  250.  
  251. 'Returns the number of logical drives. For instance- if 4 is returned
  252. 'then the valid drive names are A: B: C: & D:
  253. 'Since I only got to check this sub out with my computer's
  254. 'drive configuration, this sub checks over it's findings
  255. 'to make sure it has the correct number of logical drives.
  256. '(better safe than sorry!)
  257. FUNCTION NumDrives
  258.     DIM InReg AS Register
  259.     InReg.Ax = &HE00
  260.     InReg.Dx = ASC(CurrentDrive$) - 65
  261.     CALL interrupt(&H21, InReg, InReg)
  262.     Temp = (InReg.Ax MOD 256) - 1
  263.     FOR A = 1 TO Temp
  264.         IF LogicalDrives(CHR$(A + 64)) = -1 THEN
  265.             NumDrives = A - 1
  266.             EXIT FUNCTION
  267.         END IF
  268.     NEXT
  269.     NumDrives = Temp
  270. END FUNCTION
  271.  
  272. 'This subroutine is for the QuickSort algoritmn only.
  273. FUNCTION RandInt (Lower, Upper)
  274.     RandInt = INT(RND(1) * (Upper - Lower) + .5) + Lower
  275. END FUNCTION
  276.  
  277. 'Returns the current path in a usable form.
  278. 'WARNING: if the drive isn't ready this sub will HANG UP!!!
  279. FUNCTION RealPath$
  280.     RealPath$ = CurrentDrive$ + ":\" + CurrentPath$
  281. END FUNCTION
  282.  
  283. 'Highlights an area. Use a COLOR statement before calling.
  284. SUB Refresh (X, Y, Length)
  285.     FOR A = X TO X + Length - 1
  286.         LOCATE Y, A
  287.         PRINT CHR$(SCREEN(Y, A));
  288.     NEXT
  289. END SUB
  290.  
  291. 'Similar to the CHDIR command except this can also change the current
  292. 'drive.
  293. SUB RestorePath (A$)
  294.     ChangeDrive LEFT$(A$, 1)
  295.     CHDIR A$
  296. END SUB
  297.  
  298. 'Allows the user to select a file.
  299. 'Valid keys:
  300. 'Up, down, left, and right arrow keys move cursor.
  301. 'Tab key changes between Files and Directories windows.
  302. 'A-Z, a-z, 0-9 goes right to the next name beginning with the pressed letter.
  303. 'Home and End keys go to beginning or ending of list.
  304. 'Enter selects.
  305. 'Esc aborts.
  306. SUB SelectFile (FileName$, Status)
  307.   
  308.     'dim all arrays
  309.     REDIM EntryName$(400), Extension$(400), EntryType(400)
  310.     REDIM SortBuffer$(400)
  311.     REDIM Window$(34, 12), Direct$(100)
  312.   
  313.     
  314.     SCREEN 0, , 1, 1
  315.     CLS
  316.     COLOR 14, 0
  317.    
  318.     'make screen
  319.     MakeFrame 1, 1, 80, 24
  320.     MakeFrame 5, 7, 58, 22
  321.     MakeFrame 60, 7, 75, 22
  322.     MakeFrame 17, 2, 32, 4
  323.   
  324.    
  325.     COLOR 15
  326.     LOCATE 1, 33
  327.     PRINT " Choose File "
  328.     LOCATE 3, 5
  329.     PRINT "File Name:"
  330.     LOCATE 6, 29
  331.     PRINT "Files"
  332.     LOCATE 6, 62
  333.     PRINT "Directories"
  334.    
  335.     'If Position=1 then Cursor is at Files window, if it's 2 then
  336.     'the cursor is at the Directories window
  337.     Position = 1
  338.    
  339.     'set up path at root directory of current drive
  340.     Newpath$ = CurrentDrive$ + ":\"
  341.    
  342.     'set up default wildcard
  343.     WildCard$ = "*.*"
  344.    
  345.     DO
  346.       
  347.         'fast way of clearing arrays
  348.         ERASE Window$, Direct$
  349.         REDIM Window$(34, 12), Direct$(100)
  350.       
  351.         UseLast1 = False
  352.         UseLast2 = False
  353.        
  354.         'get current drive
  355.         Drive$ = CurrentDrive$
  356.        
  357.         'clear flag
  358.         ErrorStatus = 0
  359.                  
  360.         'see if drive is ready
  361.         ON ERROR GOTO ErrorHandler
  362.         CHDIR Newpath$
  363.         ON ERROR GOTO 0
  364.        
  365.         'if drives ready then get current path
  366.         IF ErrorStatus = 0 THEN Path$ = CurrentPath$
  367.        
  368.         'Path$ will be "" if on root directory
  369.         IF Path$ = "" THEN
  370.             FullPath$ = Drive$ + ":\" + WildCard$
  371.             Root = True
  372.         ELSE
  373.             FullPath$ = Drive$ + ":\" + Path$ + "\" + WildCard$
  374.             Root = False
  375.         END IF
  376.         'FullPath$ now has ready to use path+wildcard
  377.  
  378.         LOCATE 5, 5
  379.         PRINT FullPath$; STRING$(79 - POS(0), 32)
  380.        
  381.         'alert user if drive not ready; otherwise
  382.         'get the directory
  383.         IF ErrorStatus <> 0 THEN
  384.             SOUND 1000, 3
  385.             Num = 0
  386.             LOCATE 25, 34
  387.             COLOR 15 + 16
  388.             PRINT "Drive Error";
  389.             COLOR 15
  390.         ELSE
  391.             GetDir EntryName$(), Extension$(), EntryType(), Num, FullPath$, Status
  392.         END IF
  393.        
  394.         'set NoFiles to True so it can be proved false later
  395.         NoFiles = True
  396.        
  397.         'if Num<>0 then there are directories or files
  398.         IF Num <> 0 THEN
  399.             TempNum = 0
  400.            
  401.             'put all files in sort buffer
  402.             FOR A = 0 TO Num - 1
  403.                 IF EntryType(A) = File THEN
  404.                     SortBuffer$(TempNum) = EntryName$(A)
  405.                     IF Extension$(A) <> "" THEN
  406.                         SortBuffer$(TempNum) = SortBuffer$(TempNum) + "." + Extension$(A)
  407.                     END IF
  408.                     TempNum = TempNum + 1
  409.                 END IF
  410.             NEXT
  411.             'if there are files then QuickSort them
  412.             'and put them in a 2 dimensional array
  413.             IF TempNum <> 0 THEN
  414.               
  415.                 Sort SortBuffer$(), 0, TempNum - 1
  416.                 X = 0
  417.                 Y = 0
  418.                 FOR A = 0 TO TempNum - 1
  419.                     Window$(X, Y) = SortBuffer$(A)
  420.                     LastX = X
  421.                     LastY = Y
  422.                     Y = Y + 1
  423.                     IF Y > 11 THEN
  424.                         Y = 0: X = X + 1
  425.                     END IF
  426.                 NEXT
  427.                 NoFiles = False
  428.             END IF
  429.         END IF
  430.        
  431.         'set up directory array
  432.         DirectNum = 0
  433.         IF NOT Root THEN
  434.             Direct$(DirectNum) = ".."
  435.             DirectNum = DirectNum + 1
  436.         END IF
  437.         FOR A = 1 TO NumDrives
  438.             Direct$(DirectNum) = "[-" + CHR$(64 + A) + "-]"
  439.             DirectNum = DirectNum + 1
  440.         NEXT
  441.         FOR A = 0 TO Num - 1
  442.             IF EntryType(A) = Directory THEN
  443.                 Direct$(DirectNum) = EntryName$(A)
  444.                 DirectNum = DirectNum + 1
  445.             END IF
  446.         NEXT
  447.         Sort Direct$(), 0, DirectNum - 1
  448.  
  449.         'CurrentX and CurrentY hold cursors position in Files window
  450.         CurrentX = 0
  451.         CurrentY = 0
  452.        
  453.         'DirectNum holds maximum position if Direct$() array
  454.         DirectNum = DirectNum - 1
  455.        
  456.         'put lists on screen
  457.         GOSUB Update1
  458.         GOSUB Update2
  459.        
  460.         'clear FileName window at put new name
  461.         LOCATE 3, 19: PRINT STRING$(8 + 3 + 1, " ")
  462.         LOCATE 3, 19: PRINT Window$(0, 0)
  463.        
  464.         DO
  465.             'if there are no files then don't let cursor at Files window
  466.             IF NoFiles THEN Position = 2
  467.            
  468.             'depending on Position, go to FileWindow or DirectWindow
  469.             SELECT CASE Position
  470.                 CASE 1
  471.                     GOSUB FileWindow
  472.                 CASE 2
  473.                     GOSUB DirectWindow
  474.             END SELECT
  475.             'loop while the user just presses the TAB key
  476.         LOOP WHILE Status = 3
  477.        
  478.         'loop until the user presses ENTER or ESC
  479.     LOOP UNTIL Status <> 0
  480.    
  481.     'erase the arrays
  482.     ERASE EntryName$, Extension$, EntryType, SortBuffer$
  483. 'return to calling program
  484. EXIT SUB
  485.  
  486. 'updates the Files window with files
  487. Update1:
  488.     'switch to work screen so user gets a clean change
  489.     SCREEN 0, , 2, 1
  490.     COLOR 15, 0
  491.     'copy old screen to work screen
  492.     PCOPY 1, 2
  493.    
  494.     'start printing the file entries
  495.     RealX = 7
  496.     FOR X = CurrentX TO CurrentX + 2
  497.         FOR Y = 0 TO 11
  498.             LOCATE Y + 9, RealX
  499.             PRINT STRING$(12, 32)
  500.             LOCATE Y + 9, RealX
  501.             PRINT Window$(X, Y)
  502.         NEXT
  503.         RealX = RealX + 17
  504.     NEXT
  505.     'print location bar
  506.     LOCATE 22, 7: PRINT STRING$(50, "░")
  507.     IF LastX = 0 THEN
  508.         X = 7
  509.     ELSE
  510.         X = 7 + (CurrentX / LastX) * 49
  511.     END IF
  512.     LOCATE 22, X: PRINT "█";
  513.     'copy work screen to display screen
  514.     PCOPY 2, 1
  515.     SCREEN 0, , 1, 1
  516.     COLOR 15, 0
  517. RETURN
  518. 'updates the directory window
  519. Update2:
  520.     'print directories
  521.     RealY = 9
  522.     FOR Y = CurrentY TO CurrentY + 11
  523.         LOCATE RealY, 62
  524.         PRINT STRING$(8, 32);
  525.         LOCATE RealY, 62
  526.         PRINT Direct$(Y)
  527.         RealY = RealY + 1
  528.     NEXT
  529.     'print location bar
  530.     FOR Y = 8 TO 8 + 13
  531.         LOCATE Y, 75
  532.         PRINT "░"
  533.     NEXT
  534.     LOCATE 8 + (CurrentY / DirectNum) * 13, 75
  535.     PRINT "█"
  536. RETURN
  537. 'this sub controls the cursor when it is in the Files window
  538. FileWindow:
  539.     IF UseLast1 THEN
  540.         Xpos = LastXPos1
  541.         YPos = LastYPos1
  542.     ELSE
  543.         Xpos = 0
  544.         YPos = 0
  545.     END IF
  546.     DO
  547.         'highlight the cursors position
  548.         COLOR 0, 7
  549.         Refresh 6 + Xpos * 17, YPos + 9, 18
  550.         COLOR 15, 0
  551.        
  552.         'get the filename under the cursor
  553.         FileName$ = Window$(CurrentX + Xpos, YPos)
  554.        
  555.         'print the current file at tope
  556.         LOCATE 3, 19
  557.         PRINT STRING$(13, 32)
  558.         LOCATE 3, 19
  559.         PRINT FileName$
  560.  
  561.         'wait for a key
  562.         A = GetKey
  563.        
  564.         'clear cursor
  565.         Refresh 6 + Xpos * 17, YPos + 9, 18
  566.        
  567.         'process the key
  568.         SELECT CASE A
  569.             CASE Esc
  570.                 Status = 2
  571.                 RETURN
  572.             CASE Home
  573.                 CurrentX = 0
  574.                 Xpos = 0: YPos = 0
  575.                 GOSUB Update1
  576.             CASE EndKey
  577.                 CurrentX = LastX
  578.                 YPos = LastY
  579.                 Xpos = 0
  580.                 GOSUB Update1
  581.             CASE TabKey
  582.                 'save the cursors position
  583.                 LastXPos1 = Xpos
  584.                 LastYPos1 = YPos
  585.                 UseLast1 = True
  586.  
  587.                 Status = 3
  588.                 Position = 2
  589.                 RETURN
  590.             CASE Enter
  591.                 IF Path$ <> "" THEN
  592.                     FileName$ = Drive$ + ":\" + Path$ + "\" + FileName$
  593.                 ELSE
  594.                     FileName$ = Drive$ + ":\" + FileName$
  595.                 END IF
  596.                 Status = 1
  597.                 RETURN
  598.             CASE DownArrow
  599.                 YPos = YPos + 1
  600.                 IF Xpos + CurrentX = LastX AND YPos > LastY THEN
  601.                     YPos = LastY
  602.                 END IF
  603.                 IF YPos > 11 THEN
  604.                     YPos = 0
  605.                     Xpos = Xpos + 1
  606.                     IF Xpos > 2 THEN
  607.                         Xpos = 2
  608.                         CurrentX = CurrentX + 1
  609.                         IF CurrentX - 2 > LastX THEN
  610.                             CurrentX = LastX - 2
  611.                         END IF
  612.                         GOSUB Update1
  613.                     END IF
  614.                 END IF
  615.             CASE UpArrow
  616.                 YPos = YPos - 1
  617.                 IF YPos < 0 THEN
  618.                     IF Xpos + CurrentX = 0 THEN
  619.                         YPos = 0
  620.                     ELSE
  621.                         YPos = 11
  622.                         Xpos = Xpos - 1
  623.                         IF Xpos < 0 THEN
  624.                             Xpos = 0
  625.                             CurrentX = CurrentX - 1
  626.                             IF CurrentX < 0 THEN
  627.                                 CurrentX = 0
  628.                                 Xpos = 2
  629.                             END IF
  630.                             GOSUB Update1
  631.                         END IF
  632.                     END IF
  633.                 END IF
  634.             CASE LeftArrow
  635.                 Xpos = Xpos - 1
  636.                 IF Xpos < 0 THEN
  637.                     Xpos = 0
  638.                     IF Xpos + CurrentX = 0 THEN
  639.                         YPos = 0
  640.                     ELSE
  641.                         CurrentX = CurrentX - 1
  642.                         GOSUB Update1
  643.                     END IF
  644.                 END IF
  645.             CASE RightArrow
  646.                 Xpos = Xpos + 1
  647.                 IF Xpos + CurrentX > LastX THEN
  648.                     Xpos = LastX - CurrentX
  649.                     YPos = LastY
  650.                 END IF
  651.                 IF Xpos + CurrentX = LastX AND YPos > LastY THEN
  652.                     YPos = LastY
  653.                 END IF
  654.                 IF Xpos > 2 THEN
  655.                     Xpos = 2
  656.                     CurrentX = CurrentX + 1
  657.                     IF Xpos + CurrentX = LastX AND YPos > LastY THEN
  658.                         YPos = LastY
  659.                     END IF
  660.                     GOSUB Update1
  661.                 END IF
  662.             CASE 65 TO 90, 97 TO 122, 48 TO 57
  663.                 A$ = UCASE$(CHR$(A))
  664.                 RealX = CurrentX + Xpos
  665.                 RealY = CurrentY + YPos
  666.                 StopX = RealX
  667.                 StopY = RealY
  668.                 ScanX = RealX
  669.                 ScanY = RealY + 1
  670.                 IF ScanY > 11 THEN
  671.                     ScanY = 0
  672.                     ScanX = ScanX + 1
  673.                 END IF
  674.                 DO UNTIL ScanX > LastX OR LEFT$(Window$(ScanX, ScanY), 1) = A$
  675.                     ScanY = ScanY + 1
  676.                     IF ScanY > 11 THEN
  677.                         ScanY = 0
  678.                         ScanX = ScanX + 1
  679.                     END IF
  680.                 LOOP
  681.                 IF NOT ScanX > LastX THEN
  682.                     Xpos = 0
  683.                     YPos = ScanY
  684.                     CurrentX = ScanX
  685.                     GOSUB Update1
  686.                 ELSE
  687.                     ScanX = 0
  688.                     ScanY = 0
  689.                     DO UNTIL (ScanX = StopX AND ScanY = StopY) OR LEFT$(Window$(ScanX, ScanY), 1) = A$
  690.                         ScanY = ScanY + 1
  691.                         IF ScanY > 11 THEN
  692.                             ScanY = 0
  693.                             ScanX = ScanX + 1
  694.                         END IF
  695.                     LOOP
  696.                     IF NOT (ScanX = StopX AND ScanY = StopY) THEN
  697.                         Xpos = 0
  698.                         YPos = ScanY
  699.                         CurrentX = ScanX
  700.                         GOSUB Update1
  701.                     END IF
  702.                 END IF
  703.         END SELECT
  704.     LOOP
  705. 'this sub controls the cursor when it is in the Directories window
  706. DirectWindow:
  707.     IF UseLast2 THEN
  708.         YPos = LastYPos2
  709.     ELSE
  710.  
  711.         YPos = 0
  712.     END IF
  713.     DO
  714.         'highlight the cursors position
  715.         COLOR 0, 7
  716.         Refresh 61, YPos + 9, 14
  717.         'wait for a key
  718.         A = GetKey
  719.        
  720.         'unhighlight the cursors position
  721.         COLOR 15, 0
  722.         Refresh 61, YPos + 9, 14
  723.        
  724.         'process key
  725.         SELECT CASE A
  726.             CASE Esc
  727.                 Status = 2
  728.                 RETURN
  729.             CASE TabKey
  730.                 'see if it's ok to go to files window
  731.                 IF NOT NoFiles THEN
  732.                     'save the cursors position
  733.                     UseLast2 = True
  734.                     LastYPos2 = YPos
  735.                    
  736.                     Position = 1
  737.                     Status = 3
  738.                     RETURN
  739.                 END IF
  740.             CASE Enter
  741.                 NewDirect$ = Direct$(YPos + CurrentY)
  742.                 IF NewDirect$ = ".." THEN
  743.                     Newpath$ = ".."
  744.                     Status = 0
  745.                     RETURN
  746.                 ELSEIF LEFT$(NewDirect$, 1) = "[" THEN
  747.                     PCOPY 1, 2
  748.                     NewDrive$ = MID$(NewDirect$, 3, 1)
  749.                     ErrorStatus = 0
  750.                    
  751.                     'check drive to see if it is ready
  752.                     ON ERROR GOTO ErrorHandler
  753.                     CHDIR NewDrive$ + ":\"
  754.                     ON ERROR GOTO 0
  755.                    
  756.                     PCOPY 2, 1
  757.                     IF ErrorStatus <> 0 THEN
  758.                         SOUND 1000, 3
  759.                         LOCATE 25, 34
  760.                         COLOR 15 + 16
  761.                         PRINT "Drive Error";
  762.                         COLOR 15
  763.                     ELSE
  764.                         LOCATE 25, 34
  765.                         PRINT STRING$(11, 32);
  766.                         Newpath$ = NewDrive$ + ":\"
  767.                         ChangeDrive NewDrive$
  768.                         Status = 0
  769.                         RETURN
  770.                     END IF
  771.                 ELSE
  772.                     IF Path$ = "" THEN
  773.                         Newpath$ = Drive$ + ":\" + NewDirect$
  774.                     ELSE
  775.                         Newpath$ = Drive$ + ":\" + Path$ + "\" + NewDirect$
  776.                     END IF
  777.                     Status = 0
  778.                     RETURN
  779.                 END IF
  780.             CASE DownArrow
  781.                 YPos = YPos + 1
  782.                 IF YPos + CurrentY > DirectNum THEN
  783.                     YPos = YPos - 1
  784.                 END IF
  785.                 IF YPos > 11 THEN
  786.                     YPos = 11
  787.                     CurrentY = CurrentY + 1
  788.                     IF CurrentY + 11 > DirectNum THEN
  789.                         CurrentY = DirectNum - 11
  790.                     END IF
  791.                     GOSUB Update2
  792.                 END IF
  793.             CASE UpArrow
  794.                 YPos = YPos - 1
  795.                 IF YPos < 0 THEN
  796.                     YPos = 0
  797.                     CurrentY = CurrentY - 1
  798.                     IF CurrentY < 0 THEN
  799.                         CurrentY = 0
  800.                     END IF
  801.                     GOSUB Update2
  802.                 END IF
  803.             CASE Home
  804.                 YPos = 0
  805.                 CurrentY = 0
  806.                 GOSUB Update2
  807.             CASE EndKey
  808.                 YPos = 0
  809.                 CurrentY = DirectNum
  810.                 GOSUB Update2
  811.             CASE 65 TO 90, 97 TO 122, 48 TO 57
  812.                 A$ = UCASE$(CHR$(A))
  813.                 StopScan = YPos + CurrentY
  814.                 Scan = StopScan + 1
  815.                 DO UNTIL Scan > DirectNum OR LEFT$(Direct$(Scan), 1) = A$
  816.                     Scan = Scan + 1
  817.                 LOOP
  818.                 IF NOT Scan > DirectNum THEN
  819.                     YPos = 0
  820.                     CurrentY = Scan
  821.                     GOSUB Update2
  822.                 ELSE
  823.                     Scan = 0
  824.                     DO UNTIL Scan = StopScan OR LEFT$(Direct$(Scan), 1) = A$
  825.                         Scan = Scan + 1
  826.                     LOOP
  827.                     IF NOT Scan = StopScan THEN
  828.                         YPos = 0
  829.                         CurrentY = Scan
  830.                         GOSUB Update2
  831.                     END IF
  832.                 END IF
  833.         END SELECT
  834.     LOOP
  835.  
  836. END SUB
  837.  
  838. 'QuickSorts a string array. Low=first entry High=last entry
  839. SUB Sort (A$(), Low, High)
  840.  
  841.    IF Low < High THEN
  842.       IF High - Low = 1 THEN
  843.          IF A$(Low) > A$(High) THEN
  844.             SWAP A$(Low), A$(High)
  845.          END IF
  846.       ELSE
  847.  
  848.          RandIndex = RandInt(Low, High)
  849.          SWAP A$(High), A$(RandIndex)
  850.          Partition$ = A$(High)
  851.          DO
  852.  
  853.             I = Low: J = High
  854.             DO WHILE (I < J) AND (A$(I) <= Partition$)
  855.                I = I + 1
  856.             LOOP
  857.             DO WHILE (J > I) AND (A$(J) >= Partition$)
  858.                J = J - 1
  859.             LOOP
  860.  
  861.             IF I < J THEN
  862.                SWAP A$(I), A$(J)
  863.             END IF
  864.          LOOP WHILE I < J
  865.  
  866.          SWAP A$(I), A$(High)
  867.  
  868.          IF (I - Low) < (High - I) THEN
  869.             Sort A$(), Low, I - 1
  870.             Sort A$(), I + 1, High
  871.          ELSE
  872.             Sort A$(), I + 1, High
  873.             Sort A$(), Low, I - 1
  874.          END IF
  875.       END IF
  876.    END IF
  877. END SUB
  878.  
  879.